package com.allenkerr.util;

import com.alibaba.fastjson.JSON;
import com.allenkerr.common.ApplicationConstant.RedisKey;
import com.allenkerr.third.HistogramRetrieval;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.time.Instant;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * 测试三维彩色直方图
 * Created by 小柯 on 17/7/10.
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class ColorHistogramTest03 {

    @Test
    public void testGetBDistanceFromRgbHistogram1() throws Exception {
//        InputStream aFile = HistogramRetrieval.class.getResourceAsStream("/images/25-边牧(小图).jpeg");
//        InputStream aFile = HistogramRetrieval.class.getResourceAsStream("/images/after-01.jpg");
        InputStream aFile = HistogramRetrieval.class.getResourceAsStream("/images/787.jpg");

//        InputStream bFile = HistogramRetrieval.class.getResourceAsStream("/images/25-边牧.jpeg");
//        InputStream bFile = HistogramRetrieval.class.getResourceAsStream("/images/after-04.jpg");
        InputStream bFile = HistogramRetrieval.class.getResourceAsStream("/images/787-旋转缩小.jpg");

        BufferedImage aPic = ImageIO.read(aFile);
        BufferedImage bPic = ImageIO.read(bFile);

        double distance = ColorHistogram.getBDistanceFromOneRgbHistogram(aPic, bPic);
        System.out.println("distance = " + distance);
        //787 VS 787-旋转缩小：
        // 灰度直方图：   distance = 0.99809176831623
        // 一维彩色直方图：distance = 0.9964785490201354
        // 三维彩色直方图：distance = 0.9973638782464219
    }

    @Test
    public void testGetBDistanceFromRgbHistogram2() throws IOException {
        String aImagePath = "/Users/scw/Workspace/SpringBootDemo3/demo08-image-compare/src/test/resources/images/01-两只海豚.jpg";
        String bImagePath = "/Users/scw/Workspace/SpringBootDemo3/demo08-image-compare/src/test/resources/images/02-两只海豚.jpg";

        File aImageFile = new File(aImagePath);
        File bImageFile = new File(bImagePath);

        BufferedImage aImage = ImageIO.read(aImageFile);
        BufferedImage bImage = ImageIO.read(bImageFile);

        double distance = ColorHistogram.getBDistanceFromThreeRgbHistogram(aImage, bImage);
        System.out.println(distance);
    }

    @Test
    public void testGetBDistanceFromRgbHistogram3() throws IOException {
        String aImagePath = "/Users/scw/Workspace/SpringBootDemo3/demo08-image-compare/src/test/resources/images/01-两只海豚.jpg";
        String bImagePath = "/Users/scw/Workspace/SpringBootDemo3/demo08-image-compare/src/test/resources/images/02-两只海豚.jpg";
        double distance = ColorHistogram.getBDistanceFromThreeRgbHistogram(aImagePath, bImagePath);
        System.out.println(distance);
    }

    public static String getFileName(String filePath) {
        return filePath.substring(filePath.lastIndexOf("/") + 1);
    }

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 获取图片的三维彩色直方图，并存入 config 中
     */
    @Test
    public void testGetRgbHistogram() {
        Instant startTime = Instant.now();

        //获取 images
        final String imagesDirPath = "/Users/scw/Workspace/SpringBootDemo3/demo08-image-compare/src/test/resources/images";
        File imagesDir = new File(imagesDirPath);
        List<String> images = new LinkedList<>();
        FileUtils.getFilePathList(imagesDir, images);
        int size = images.size();

        for (int i = 0; i < size; i++) {
            String imagePath = images.get(i);
            String imageName = getFileName(imagePath);
            BufferedImage image = ImageUtils.getBufferedImage(imagePath);

            //获取 RgbHistogram
            ColorHistogram.HistogramData histogramData = ColorHistogram.getThreeRgbHistogramData(image);
            System.out.println(imageName + " --> " + JSON.toJSONString(histogramData));

            //存入 config
            redisTemplate.opsForHash().put(RedisKey.THREE_RGB_HISTOGRAM_MAP, imageName, histogramData);
        }

        Instant endTime = Instant.now();
        long time = Duration.between(startTime, endTime).toMillis();
        System.out.println("处理 " + size + " 张图片，耗时：" + time + " 毫秒，平均 " + time * 1.0 / size + " 张/ms");
        /**
         * 处理并存储：   处理 35 张图片，耗时：5681 毫秒，平均 162.31428571428572 张/ms
         */
    }

    @Test
    public void testGetBDistance() {
        Instant startTime = Instant.now();

        Map<String, ColorHistogram.HistogramData> entries = redisTemplate.opsForHash().entries(RedisKey.THREE_RGB_HISTOGRAM_MAP);

        //外层循环
        for (Map.Entry<String, ColorHistogram.HistogramData> outerEntry : entries.entrySet()) {
            String aImageName = outerEntry.getKey();
            ColorHistogram.HistogramData aData = outerEntry.getValue();

            System.out.println("比较主体：" + aImageName);
            //构建一个 TreeMap
            TreeMap<Double, String> distanceMap = new TreeMap<>((x, y) -> -Double.compare(x, y));
            //内层循环
            for (Map.Entry<String, ColorHistogram.HistogramData> innerEntry : entries.entrySet()) {
                String bImageName = innerEntry.getKey();
                ColorHistogram.HistogramData bData = innerEntry.getValue();

                //获取巴氏距离
                double distance = ColorHistogram.getBhattacharyyaDistance(aData, bData);

                distanceMap.put(distance, bImageName);
            }
            for (Map.Entry<Double, String> entry : distanceMap.entrySet()) {
                System.out.println("\t\t" + entry.getKey() + "  ---->  " + entry.getValue());
            }
            System.out.println("---------------------------------\n");
        }

        Instant endTime = Instant.now();
        long time = Duration.between(startTime, endTime).toMillis();
        int count = entries.size() * entries.size();
        System.out.println("比较 " + count + " 次，耗时：" + time + " 毫秒，平均 " + time * 1.0 / count + " 张/ms");
        /**
         * 比较 1225 次，耗时：458 毫秒，平均 0.37387755102040815 张/ms
         */
    }

    @Test
    public void testGetBDistanceFromRgbHistogram5() {
        Instant startTime = Instant.now();

        //获取 examples
        final String examplesDirPath = "/Users/scw/Workspace/SpringBootDemo3/demo08-image-compare/src/test/resources/examples";
        File examplesDir = new File(examplesDirPath);
        List<String> examples = new LinkedList<>();
        FileUtils.getFilePathList(examplesDir, examples);

        //config
        Map<String, ColorHistogram.HistogramData> entries = redisTemplate.opsForHash().entries(RedisKey.THREE_RGB_HISTOGRAM_MAP);

        for (String example : examples) {
            String exampleName = getFileName(example);
            BufferedImage bufferedImage = ImageUtils.getBufferedImage(example);
            ColorHistogram.HistogramData histogramData = ColorHistogram.getThreeRgbHistogramData(bufferedImage);

            System.out.println("比较主体：" + exampleName);

            //构建一个 TreeMap
            TreeMap<Double, String> distanceMap = new TreeMap<>((x, y) -> -Double.compare(x, y));

            //内层循环
            for (Map.Entry<String, ColorHistogram.HistogramData> entry : entries.entrySet()) {
                double distance = ColorHistogram.getBhattacharyyaDistance(histogramData, entry.getValue());
                if (distance >= 0.9) {
                    distanceMap.put(distance, entry.getKey());
                }
            }
            //打印结果
            for (Map.Entry<Double, String> entry : distanceMap.entrySet()) {
                System.out.println("\t\t" + entry.getKey() + "  ---->  " + entry.getValue());
            }
            System.out.println("---------------------------------\n");
        }

        Instant endTime = Instant.now();
        long time = Duration.between(startTime, endTime).toMillis();
        int count = examples.size() * entries.size();
        System.out.println("比较 " + count + " 次，耗时：" + time + " 毫秒，平均 " + time * 1.0 / count + " 张/ms");
        /**
         * 比较 280 次，耗时：1073 毫秒，平均 3.8321428571428573 张/ms
         */
    }

}